package com.fagu.openerp;

import java.io.File;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.log4j.Logger;

public class Mail {
	private Properties properties = new Properties();
	
	private final String MAIL_PROPERTIES_PATH = "/com/fagu/openerp/properties/Mail.properties";
	
	private Session session;
	
	private Logger log = Logger.getLogger(getClass().getName());
	
	private BodyPart attach = null;
	private BodyPart text = null;
	private MimeMessage msg = null;
	
	private boolean isAttachFileSet = false;
	private boolean isSubjectSet = false;
	private boolean isTextSet = false;
	private boolean isRecipientsSet = false;

	public Mail() {
		init();
	}
	
	public Mail(String message, String subject, File file) {
		init();
		setMessage(message);
		setSubject(subject);
		addRecipients();
		attachFile(file);
	}
	
	public Mail(String message, String subject) {
		init();
		setMessage(message);
		setSubject(subject);
		addRecipients();
	}
	
	private void init() {
		properties = MyProperties.getProperties(MAIL_PROPERTIES_PATH);
		
		session = Session.getDefaultInstance(properties);
		msg = new MimeMessage(session);
		
		try {
			msg.setFrom(new InternetAddress((String)properties.get("mail.smtp.mail.sender")));
		} catch (AddressException e) {
			log.error(e.getNextException());
		} catch (MessagingException e) {
			log.error(e.getMessage());
		}
	}

	/**
	 * Send the e-mail
	 */
	public void send() {
		try {
			// Build Message
			MimeMultipart multiPart = new MimeMultipart();
			// Attachment
			if (isAttachFileSet)
				multiPart.addBodyPart(attach);
			// Text
			if (isTextSet)
				multiPart.addBodyPart(text);
			else
				log.warn("E-mail without message.");
			// Subject
			if (!isSubjectSet)
				log.warn("E-mail without subject.");
			// Recipients
			if (!isRecipientsSet) {
				log.error("Unable to send mail. E-mail without recipients.");
				return;
			} else {
				if (msg.getRecipients(RecipientType.TO) != null)
					for (Address to : msg.getRecipients(RecipientType.TO))
						log.info("Sending mail TO: " + to.toString());
				if (msg.getRecipients(RecipientType.CC) != null)
					for (Address cc : msg.getRecipients(RecipientType.CC))
						log.info("Sending mail CC: " + cc.toString());
				if (msg.getRecipients(RecipientType.BCC) != null)
					for (Address bcc : msg.getRecipients(RecipientType.BCC))
						log.info("Sending mail BCC: " + bcc.toString());
			}
			
			msg.setContent(multiPart, "text/html");
			Transport t = session.getTransport("smtp");
			t.connect((String) properties.get("mail.smtp.user"), (String) properties.get("mail.smtp.password"));
			t.sendMessage(msg, msg.getAllRecipients());
			t.close();
		} catch (MessagingException eMsg) {
			log.error(eMsg.getMessage());
		}
	}

	/**
	 * Add recipients to the mail
	 * @param recipients
	 */
	public void addRecipients() {
		// TO
		String tos = (String) properties.get("mail.to");
		StringTokenizer st = new StringTokenizer(tos, ",");
		while (st.hasMoreElements()){
			try {
			msg.addRecipient(RecipientType.TO, new InternetAddress(st.nextElement().toString()));
			} catch (AddressException e) {
				log.error(e.getMessage());
			} catch (MessagingException e) {
				log.error(e.getMessage());
			}
		}
		
		// CC
		String ccs = (String) properties.get("mail.cc");
		st = new StringTokenizer(ccs, ",");
		while (st.hasMoreElements()) {
			try {
				msg.addRecipient(RecipientType.CC, new InternetAddress(st.nextElement().toString()));
			} catch (AddressException e) {
				log.error(e.getMessage());
			} catch (MessagingException e) {
				log.error(e.getMessage());
			}
		}

		// BCC
		String bccs = (String) properties.get("mail.bcc");
		st = new StringTokenizer(bccs, ",");
		while (st.hasMoreElements()) {
			try {
				msg.addRecipient(RecipientType.BCC, new InternetAddress(st.nextElement().toString()));
			} catch (AddressException e) {
				log.error(e.getMessage());
			} catch (MessagingException e) {
				log.error(e.getMessage());
			}
		}
		
		isRecipientsSet = true;
	}
	
	/**
	 * Set the subject of the mail
	 * @param subject
	 */
	public void setSubject(String subject) {
		try {
			msg.setSubject(subject);
		} catch (MessagingException e) {
			log.error(e.getMessage());
		}
		isSubjectSet = true;
	}
	
	/**
	 * Set the body text of the mail
	 * @param message
	 */
	public void setMessage(String message) {
		text = new MimeBodyPart();
		try {
			text.setText(message);
		} catch (MessagingException e) {
			log.error(e.getMessage());
		}
		isTextSet = true;
	}
	
	/**
	 * Attach file to the mail
	 * @param file
	 */
	public void attachFile(File file) {
		attach = new MimeBodyPart();
		try {
			attach.setDataHandler(new DataHandler(new FileDataSource(file)));
			attach.setFileName(file.getName());
		} catch (MessagingException e) {
			log.error(e.getMessage());
		}
		isAttachFileSet = true;
	}
	
}
